﻿
#region License, Terms and Conditions
//
// IntercomApiBase.cs
//
// Authors: Kori Francis <twitter.com/djbyter>
// Copyright (C) 2012 Kori Francis. All rights reserved.
// 
// THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
#endregion

namespace Intercom.Core
{
    #region Imports
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using RestSharp;
    #endregion

    /// <summary>
    /// TODO
    /// </summary>
    public class IntercomApiBase
    {
        #region Properties and Accessors
        protected string AuthUsername { get; private set; }
        protected string AuthPassword { get; private set; }

        private static string _userAgent;
        private static string UserAgent
        {
            get
            {
                if (_userAgent == null)
                {
                    _userAgent = String.Format("Intercom .NET Client v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString());
                }
                return _userAgent;
            }
        }
        #endregion

        #region Constructor
        protected IntercomApiBase(string username, string password)
        {
            if (string.IsNullOrEmpty(username))
                throw new ArgumentException("Username is required. Details can be found at http://docs.intercom.io/api#authentication", "username");

            this.AuthUsername = username;
            this.AuthPassword = password;
        }
        #endregion

        protected T GetRequest<T>(string path, params object[] args) where T : new()
        {
            RestClient client = new RestClient(Config.ApiBaseUrl);
            client.Authenticator = new HttpBasicAuthenticator(this.AuthUsername, this.AuthPassword);
            client.UserAgent = IntercomApiBase.UserAgent;
            
            RestRequest request = new RestRequest(BuildUrl(path, args));
            request.RequestFormat = DataFormat.Json;

            var response = client.Execute<T>(request);

            if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                throw new IntercomException("Not Found");
            }
            else if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError)
            {
                throw new IntercomException("Internal Server Error");
            }

            return response.Data;
        }

        protected string GetRequest(string path, params object[] args)
        {
            RestClient client = new RestClient(Config.ApiBaseUrl);
            client.Authenticator = new HttpBasicAuthenticator(this.AuthUsername, this.AuthPassword);
            client.UserAgent = IntercomApiBase.UserAgent;

            RestRequest request = new RestRequest(BuildUrl(path, args));
            request.RequestFormat = DataFormat.Json;
            
            var response = client.Execute(request);

            if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                throw new IntercomException("Not Found");
            }
            else if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError)
            {
                throw new IntercomException("Internal Server Error");
            }

            return response.Content;
        }

        protected TOutput PutRequest<TOutput, TInput>(TInput obj, string path, params object[] args) where TOutput : new()
        {
            return Request<TOutput, TInput>(Method.PUT, obj, path, args);
        }

        protected TOutput PostRequest<TOutput, TInput>(TInput obj, string path, params object[] args) where TOutput : new()
        {
            return Request<TOutput, TInput>(Method.POST, obj, path, args);
        }

        protected void DeleteRequest(string path, params object[] args)
        {
            Request<List<object>, object>(Method.DELETE, null, path, args);
        }

        private TOutput Request<TOutput, TInput>(Method method, TInput obj, string path, params object[] args) where TOutput : new()
        {
            RestClient client = new RestClient(Config.ApiBaseUrl);
            client.Authenticator = new HttpBasicAuthenticator(this.AuthUsername, this.AuthPassword);
            client.UserAgent = IntercomApiBase.UserAgent;

            RestRequest request = new RestRequest(BuildUrl(path, args), method);
            request.RequestFormat = DataFormat.Json;
            request.JsonSerializer = new JsonSerializer();

            if (obj != null)
            {
                request.AddBody(obj);
            }

            var response = client.Execute<TOutput>(request);

            if (response.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                throw new IntercomException("Not Found");
            }
            else if (response.StatusCode == System.Net.HttpStatusCode.InternalServerError)
            {
                throw new IntercomException("Internal Server Error");
            }

            return response.Data;
        }

        protected string BuildUrl(string path, params object[] args)
        {
            // Assume for now that no querystring is added
            path = string.Format(path, args);

            return path;
        }
    }
}
